﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Threading;

namespace FriendlyFire
{
    public delegate void delReceiveWebRequest(HttpListenerContext Context);

    class FFListenerController
    {
        private HttpListener listener;
        private bool isStarted = false;
        private event delReceiveWebRequest ReceiveWebRequest;
        private FriendlyFire ffParent;

        #region Constructor
        public FFListenerController()
        {
            System.Threading.ThreadPool.SetMaxThreads(50, 1000);
            System.Threading.ThreadPool.SetMinThreads(50, 50);
        }
        #endregion
        #region Accessors
        public FriendlyFire FFParent
        {
            get { return ffParent; }
            set { ffParent = value; }
        }
        public bool IsStarted
        {
            get { return isStarted; }
            set { isStarted = value; }
        }
        public HttpListener Listener
        {
            get { return listener; }
            set { listener = value; }
        }
        #endregion
        #region Config and Start Listener
        public void Start()
        {
            string[] prefs = { "http://*:9000/", "http://*:9001/", "http://*:9002/", "http://*:9003/" };
            // *** Already running - just leave it in place
            if (this.IsStarted)
                return;

            if (this.Listener == null)
            {
                this.Listener = new HttpListener();

            }
            foreach (string s in prefs)
                this.Listener.Prefixes.Add(s);

            this.IsStarted = true;
            this.Listener.Start();
            IAsyncResult result = this.Listener.BeginGetContext(new AsyncCallback(WebRequestCallback), this.Listener);
        }
        #endregion
        #region Finish all connections and shutdown.
        public void Stop()
        {
            if (Listener != null)
            {
                this.Listener.Close();
                this.Listener = null;
                this.IsStarted = false;
            }
        }
        #endregion
        #region Async Callback
        protected void WebRequestCallback(IAsyncResult result)
        {
            if (this.Listener == null)
                return;
            // Get out the context object
            HttpListenerContext context = this.Listener.EndGetContext(result);
            // *** Immediately set up the next context
            this.Listener.BeginGetContext(new AsyncCallback(WebRequestCallback), this.Listener);
            if (this.ReceiveWebRequest != null)
                this.ReceiveWebRequest(context);
            
            this.ProcessRequest(context);
        }
        #endregion
        #region Process Requests
        public void ProcessRequest(HttpListenerContext context)
        {
            string msg = context.Request.HttpMethod + " " + context.Request.Url;
            Console.WriteLine(msg);
            StringBuilder sb = new StringBuilder();
            string[] cmd = context.Request.RawUrl.Split('/');
            if (!cmd[1].Equals("")) // command 0 and 1 will be "" if no path is in the request and therefore invalid
            {
                // make a decision based on the command verb (cmd[1]).
                // any items in the cmd array after cmd[1] are to be considered paramters to the verb.
                //ex http://localhost/search/independence%20day (note the html encoded spaces).
                // 'search' would be in cmd[1] and 'independence day' is the first paramter.
                switch (cmd[1])
                {
                    case "file":
                        sb.Append(HandleFile(cmd));
                        break;
                    case "search":
                        sb.Append(HandleSearch(cmd));
                        break;
                    case "say":
                        sb.Append(HandleSay(cmd));
                        break;
                    default:
                        sb.Append("invalid request");
                        break;
                }
            }
            else { sb.Append("invalid request"); }

            // convert to bytesteam
            byte[] b = Encoding.UTF8.GetBytes(sb.ToString());
            context.Response.SendChunked = true;
            context.Response.ContentLength64 = b.Length;
            context.Response.OutputStream.Write(b, 0, b.Length);
            context.Response.OutputStream.Close();
        }
        #endregion

        #region Handle Specific Cases
        #region File Request'/file/id#'
        private string HandleFile(string[] cmd)
        {
            return "";
        }
        #endregion
        #region Search Request '/search/params...'
        private string HandleSearch(string[] cmd)
        {
            return "";
        }
        #endregion
        #region Chat Say '/say/msg'
        private string HandleSay(string[] cmd)
        {

            return "ok";
        }
        #endregion
        #endregion
    }
}
